#include <iostream>
#include <string>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

const static int gmax_retry_fre = 5;
const static int gretry_time = 3;
const static int default_retry_fre = 0;

class TcpConnect
{
public:
    TcpConnect(uint16_t port, std::string ip, int max_retry_fre = gmax_retry_fre, int retry_time = gretry_time)
        : _con_st(Status::New), _retry_fre(default_retry_fre), _serverport(port), _serverip(ip), _max_retry_fre(max_retry_fre), _retry_time(retry_time)
    {
    }
    void Connect() // TODO server struct
    {
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_sockfd < 0)
        {
            //... TODO
            std::cout << "sockfd error" << std::endl;
        }

        sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_port = htons(_serverport);
        inet_pton(AF_INET, _serverip.c_str(), &server.sin_addr);

        int n = connect(_sockfd, (struct sockaddr *)&server, sizeof(server));
        _con_st = Status::Connecting;
        if (n < 0)
        {
            _con_st = Status::Reconnect;
        }
        else
        {
            _con_st = Status::Connected;
        }
    }

    void Reconnect()
    {
        while (_retry_fre < _max_retry_fre)
        {
            ++_retry_fre;
            _con_st = Status::Connecting;
            Connect();
            sleep(_retry_time);
            if (_con_st == Status::Connected)
                return;
            std::cout << "断线重连ing..." << "当前重连次数为:" << _retry_fre << " 最大重连次数为:" << _max_retry_fre << std::endl;
        }
        _con_st = Status::Disconnect;
    }

    void Disconnect()
    {
        ::close(_sockfd);
        _con_st = Status::Disconnect;
    }

    ~TcpConnect()
    {
        Disconnect();
    }

public:
    enum class Status
    {
        New,
        Connecting,
        Connected,
        Reconnect,
        Disconnect,
        Close
    };

public:
    Status GetStatus()
    {
        return _con_st;
    }

private:
    Status _con_st;     // 连接状态
    int _max_retry_fre; // 最大重连次数
    int _retry_fre;     // 重连次数
    int _retry_time;    // 重连时间
    int _sockfd;

private:
    uint16_t _serverport;
    std::string _serverip;
};